package com.ck.common.utils.file;

import com.ck.common.entity.CfgXhzwEntity;
import com.ck.common.utils.db.JDBCDruidUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author changk
 * @date 2024/9/4 9:13
 */
@Slf4j
public class UnzipFileUtil {

    //读取指定目录下的所有.tar.gz文件
    public static List<File> getAllTarGzFile(String directoryPath) throws IOException {
        // 尝试获取目录路径下所有.tar.gz文件
        try (Stream<Path> paths = Files.walk(Paths.get(directoryPath))) {
            // 筛选出行的是普通文件的路径
            return paths.filter(Files::isRegularFile)
                    // 进一步筛选出以.tar.gz结尾的文件路径
                    .filter(path -> path.toString().endsWith(".tar.gz"))
                    // 将路径转换为File对象
                    .map(Path::toFile)
                    // 将筛选出的File对象收集到列表中并返回
                    .collect(Collectors.toList());
        }

    }

    //解压.tar.gz文件
    public static List<File> extractTarGz(File tarGzFile,String targetDirectoryPath) throws IOException {
        // 创建一个文件列表，用于存储解压后的文件
        List<File> extractedFiles = new ArrayList<>();
        // 使用try-with-resources语句打开输入流，自动关闭资源
        try (FileInputStream fis = new FileInputStream(tarGzFile);
             GzipCompressorInputStream gis = new GzipCompressorInputStream(fis);
             TarArchiveInputStream tis = new TarArchiveInputStream(gis)) {

            // 逐个读取tar.gz文件中的条目
            TarArchiveEntry entry;
            while ((entry = tis.getNextTarEntry()) != null) {
                // 如果是目录则跳过
                if (entry.isDirectory()) {
                    continue;
                }
                // 构造解压文件的完整路径
                File outputFile = new File(targetDirectoryPath, entry.getName());
                // 确保文件的父目录存在，如果不存在则创建
                outputFile.getParentFile().mkdirs();

                // 使用OutputStream将解压的数据写入文件
                try (OutputStream os = Files.newOutputStream(outputFile.toPath())) {
                    // 定义缓冲区
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    // 读取数据并写入文件，直到没有数据可读
                    while ((bytesRead = tis.read(buffer)) != -1) {
                        os.write(buffer, 0, bytesRead);
                    }
                    // 将解压后的文件添加到列表中
                    extractedFiles.add(outputFile);
                }
            }
        }
        // 返回解压后的文件列表
        return extractedFiles;
    }

    //解析数据内容规范后并插入表中
    public static List<CfgXhzwEntity> parseFile(File file) throws IOException {
        List<CfgXhzwEntity> dataList = new ArrayList<>();
        // 假设文件是CSV格式，根据实际情况解析文件
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            boolean isFirstLine=true;
            // 每次处理一万条数据
            int batchSize = 10000;
            int count = 0;
            while ((line = reader.readLine()) != null) {
                if (isFirstLine){
                    isFirstLine=false;
                    continue;
                }
                String[] values = line.split(",");
                CfgXhzwEntity CfgXhzwEntity = new CfgXhzwEntity();
                CfgXhzwEntity.setNpNum(values[0]);
                CfgXhzwEntity.setCarryOut(values[1]);
                CfgXhzwEntity.setCarryIn(values[2]);
                CfgXhzwEntity.setIp(values[3]);

                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                LocalDateTime localDateTime=LocalDateTime.parse(values[4],df);
                Date time= Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
                CfgXhzwEntity.setDate(time);
                CfgXhzwEntity.setCsmsId(file.getName());
                dataList.add(CfgXhzwEntity);
                count++;

                if (count % batchSize == 0){
                    insertDataIntoDb(dataList);
                    dataList.clear();
                }
            }
            if (!dataList.isEmpty()){
                insertDataIntoDb(dataList);
            }
            reader.close();
        }
        return dataList;
    }


    public static void insertDataIntoDb(List<CfgXhzwEntity> dataList) {
        long startTime = System.currentTimeMillis();
        log.info(dataList.size() + "条,开始导入到数据库时间:" + startTime/1000.0 + "s");
        String insertSQL = "INSERT INTO cfg_xhzw (np_num, carry_out,carry_in,ip,csms_id,create_time,delete_time,update_time,status) VALUES";
        insertSQL += " (?,?,?,?,?,?,?,?,?)";
        String selectSQL = "SELECT * FROM cfg_xhzw WHERE np_num=?";

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        PreparedStatement selectStatement = null;
        try {
            connection = JDBCDruidUtils.getConnection();
            preparedStatement = connection.prepareStatement(insertSQL);
            selectStatement = connection.prepareStatement(selectSQL);
            connection.setAutoCommit(false);
            for (CfgXhzwEntity data : dataList) {
                selectStatement.setString(1, data.getNpNum());
                ResultSet resultSet = selectStatement.executeQuery();
                if (resultSet.next()) {
                    log.info("数据已存在，跳过: " + data.getNpNum());
                    continue;
                }
                preparedStatement.setString(1, data.getNpNum());
                preparedStatement.setString(2, data.getCarryOut());
                preparedStatement.setString(3, data.getCarryIn());
                preparedStatement.setString(4, data.getIp());
                preparedStatement.setString(5, data.getCsmsId());
                preparedStatement.setTimestamp(6, new Timestamp(data.getDate().getTime()));
                preparedStatement.setTimestamp(7, null);
                preparedStatement.setTimestamp(8, new Timestamp(data.getDate().getTime()));
                preparedStatement.setString(9, "1");
                // 添加到批处理
                preparedStatement.addBatch();
            }
            preparedStatement.executeBatch();
            connection.commit();
            long endTime = System.currentTimeMillis();
            log.info(dataList.size() + "条,结束导入到数据库时间:" + endTime/1000.0 + "s");
            log.info(dataList.size() + "条,导入用时:" + (endTime - startTime) / 1000.0 + "s");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        finally {
            JDBCDruidUtils.close(connection, preparedStatement);
        }
    }

    public static void processFile(File allTarGzFile, String directoryPath)throws IOException {
        List<File> extractFiles = extractTarGz(allTarGzFile, directoryPath);
        for (File file : extractFiles) {
            parseFile(file);
        }
    }
}
